
import { _decorator, Component, Node, Mesh, MeshRenderer, utils, gfx, Vec4, director, pipeline } from 'cc';
import GlobalPool from '../Script/Common/GlobalPool';
import yyComponent from '../Script/Common/yyComponent';
const { ccclass, property, executeInEditMode } = _decorator;
/**带速度的特效粒子 */
@ccclass('ParticleVecItem')
// @executeInEditMode
export class ParticleVecItem extends yyComponent {

    public init() {
        this.initMesh();
    }

    public play() {
        let t = director.root.cumulativeTime;
        let index = 0;
        for (let i = 0; i < this.particleCount; ++i) {
            index = i * 16 + 3;
            this.meshData.customAttributes[attributeType.time].values[index] = t;
            this.meshData.customAttributes[attributeType.time].values[index + 4] = t;
            this.meshData.customAttributes[attributeType.time].values[index + 8] = t;
            this.meshData.customAttributes[attributeType.time].values[index + 12] = t;
        }
        this.applyMesh();
        this.scheduleOnce(this.onPlayFinish, this.duartion);
    }
    protected onPlayFinish() {
        // GlobalPool.put(this.node);
    }

    /**粒子数量 */
    protected particleCount: number = 1;
    /**动画持续的时间 */
    protected duartion: number = 0;

    /**子类实现，创建粒子运动动画 */
    protected createAnim() { }
    /**
     * 设置粒子的动画数据（只缓存数据，不会应用到网格）
     * @param index 粒子索引
     * @param Pos xy:起点坐标，zw:终点坐标，局部坐标系
     * @param lineVec  //线性速度
     * @param dampingVec  //线性衰减
     * @param Time xyz:坐标、缩放、透明度变化持续时间，秒；w:开始播放时游戏累计经过的时间，秒
     * @param Ease xyz:位移缓动曲线类型，缩放、透明度缓动曲线类型；
     */
    protected cacheParticleAnim(
        index: number, Pos: number[], lineVec: number[], dampingVec: number[],
        angVec: number[], angDamping: number[], Time: number[], Ease: number[]) {
        let time = [1 / Time[0], 1 / Time[1], 1 / Time[2], 0];
        let offset = index * 16;
        for (let i = 0; i < 4; ++i) {
            offset = index * 16 + i * 4;
            for (let j = 0; j < 4; ++j) {
                //锚点坐标
                this.meshData.customAttributes[attributeType.centerPos].values[offset + j] = Pos[j];
                //线性速度
                this.meshData.customAttributes[attributeType.lineVec].values[offset + j] = lineVec[j];
                //线性衰减
                this.meshData.customAttributes[attributeType.damping].values[offset + j] = dampingVec[j];
                //角速度
                this.meshData.customAttributes[attributeType.angVec].values[offset + j] = angVec[j];
                //角速度衰减
                this.meshData.customAttributes[attributeType.angDamping].values[offset + j] = angDamping[j];
                //动画时长
                this.meshData.customAttributes[attributeType.time].values[offset + j] = time[j];
                //缓动曲线
                this.meshData.customAttributes[attributeType.ease].values[offset + j] = Ease[j];
            }
        }
        if (this.duartion < Time[0]) {
            this.duartion = Time[0];
        }
        if (this.duartion < Time[1]) {
            this.duartion = Time[1];
        }
        if (this.duartion < Time[2]) {
            this.duartion = Time[2];
        }
    }

    //#region 模型材质
    @property(MeshRenderer)
    protected meshRender: MeshRenderer = null;
    protected meshData: { positions: number[], uvs: number[], indices: number[], customAttributes?: any[] } = null;
    protected mesh: Mesh = null;
    protected initMesh() {
        this.createMesh();
        this.createAnim();
    }
    protected createMesh() {
        this.meshData = {
            positions: [],
            indices: [],
            uvs: [],
            customAttributes: [],
        };

        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.ease));
        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.centerPos));
        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.lineVec));
        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.damping));
        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.angVec));
        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.angDamping));
        this.meshData.customAttributes.push(this.createCustomAttribute(attributeType.time));

        for (let i = 0; i < this.particleCount; ++i) {
            this.addPositions();
            let index = i * 4;
            this.meshData.indices.push(
                index + 0, index + 1, index + 2,
                index + 0, index + 2, index + 3,
            );
            let uv = this.getUv();
            uv.forEach(e => {
                this.meshData.uvs.push(e);
            })

            for (let j = this.meshData.customAttributes.length - 1; j >= 0; --j) {
                this.meshData.customAttributes[j].values.push(
                    0, 0, 0, 0,
                    0, 0, 0, 0,
                    0, 0, 0, 0,
                    0, 0, 0, 0
                );
            }
        }

        this.mesh = new Mesh();
        this.mesh = utils.createMesh(this.meshData);
        this.meshRender.mesh = this.mesh;
    }
    //九宫格UV-逆时针
    protected getUv(index?: number) {
        if (undefined == index) {
            index = Math.floor(Math.random() * 9);
        }
        //3*3 uv
        let n = 3;
        let w = 1 / n;
        let h = 1 / n;
        let uvs = [
            [0, 0, w, 0, w, h, 0, h],
            [w, 0, w * 2, 0, w * 2, h, w, h],
            [w * 2, 0, 1, 0, 1, h, w * 2, h],
            [0, h, w, h, w, h * 2, 0, h * 2],
            [w, h, w * 2, h, w * 2, h * 2, w, h * 2],
            [w * 2, h, 1, h, 1, h * 2, w * 2, h * 2],
            [0, h * 2, w, h * 2, w, 1, 0, 1],
            [w, h * 2, w * 2, h * 2, w * 2, 1, w, 1],
            [w * 2, h * 2, 1, h * 2, 1, 1, w * 2, 1]
        ];
        return uvs[index];
    }

    protected addPositions(r: number = 0.5) {
        this.meshData.positions.push(
            -r, r, 0,
            -r, -r, 0,
            r, -r, 0,
            r, r, 0,
        );
    }

    protected createCustomAttribute(type: attributeType) {
        return {
            attr: {
                format: gfx.Format.RGBA32F,
                isNormalized: false,
                // stream: 0,
                sInstanced: false,
                // location: 0,
                name: attributeName[type],
            },
            values: [],
        };
    }
    protected setCustomAttributes(type: attributeType, values: number[]) {
        let data = this.meshData.customAttributes[type];
        for (let i = 0, c = data.values.length; i < c; ++i) {
            data.values[i] = values[i];
        }
        this.applyMesh();
    }
    protected applyMesh() {
        utils.createMesh(this.meshData, this.mesh);
        this.meshRender.mesh = this.mesh;
    }
    //#endregion

}

enum attributeType {
    ease,
    centerPos,
    lineVec,
    damping,
    angVec,
    angDamping,
    time,
};

const attributeName = [
    "a_actionEase",
    "a_centerPos",  //锚点坐标
    "a_lineVec",    //线性速度
    "a_damping",    //线性衰减   
    "a_angVec",     //角速度
    "a_angDamping", //角速度衰减
    "a_time"
];

